//=========================================================================
// Copyright (C) 2024 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

/**
 * ### 测试要点总结
 * 1. **正确性：** 确保基本功能测试通过。
 * 2. **性能：** 对比性能是否符合预期。
 * 3. **边界条件：** 处理空字符串、大字符串、异常情况等。
 * 4. **线程安全：** 在多线程环境下确保稳定性。
 * 5. **内存管理：** 使用工具检查是否有泄漏。
 *
 * 这些测试函数基本覆盖了自定义分配器在 `std::string` 中的常见使用场景和极限情况。
 */

#include <chrono>
#include <iostream>
#include <cassert>
#include <string>
#include <thread>
#include <vector>
#include <thread>
#include "../tlsf/TlsfStdString.h"

using namespace como;

/**
 * ### 1. **基础功能测试**
 *
 * 验证自定义分配器是否正确支持 `std::string` 的基本操作。
 */
void test_basic_operations()
{
    TlsfString str1("Hello");
    TlsfString str2("World");

    // 连接字符串
    str1 += " ";
    str1 += str2;
    assert(str1 == "Hello World");

    // 插入操作
    str1.insert(6, "Beautiful ");
    assert(str1 == "Hello Beautiful World");

    // 子串操作
    TlsfString sub = str1.substr(6, 9);
    assert(sub == "Beautiful");

    // 清空操作
    str1.clear();
    assert(str1.empty());
    std::cout << "Basic operations test passed.\n";
}

/**
 * ### 2. **大数据测试**
 *
 * 测试分配器在处理大量数据时的稳定性。
 */
void test_large_string()
{
    const size_t large_size = 10 * 1024 * 1024; // 10 MB
    TlsfString large_string;

    // 分配大字符串
    large_string.resize(large_size, 'A');
    assert(large_string.size() == large_size);

    // 修改部分数据
    large_string[0] = 'B';
    large_string[large_size - 1] = 'Z';
    assert(large_string[0] == 'B');
    assert(large_string[large_size - 1] == 'Z');

    std::cout << "Large string test passed.\n";
}

/**
 * ### 3. **多线程测试**
 *
 * 验证分配器在多线程环境下的行为（如果支持）。
 */

void thread_task(TlsfString& shared_string)
{
    for (int i = 0; i < 1000; ++i) {
        shared_string += 'A';
    }
}

void test_multithreading()
{
    TlsfString shared_string;

    // 启动多个线程
    const int thread_count = 4;
    std::vector<std::thread> threads;

    for (int i = 0;  i < thread_count;  ++i) {
        threads.emplace_back(thread_task, std::ref(shared_string));
    }

    for (auto& t : threads) {
        t.join();
    }

    assert(shared_string.size() == 4000); // 每个线程添加 1000 个字符
    std::cout << "Multithreading test passed.\n";
}


/**
 * ### 4. **性能测试**
 *
 * 对比自定义分配器和默认分配器的性能。
 */
template <typename StringType>
void performance_test(const std::string& description)
{
    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < 100000; ++i) {
        StringType str;
        str = "Tongji ";
        for (int j = 0; j < 100; j++) {
            str += "University";
        }
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end - start;
    std::cout << description << " took " << elapsed.count() << " seconds.\n";
}

void test_performance() {
    performance_test<std::string>("Default std::string");
    performance_test<TlsfString>("Custom std::string with allocator");
}

/**
 * ### 5. **边界条件测试**
 *
 * 验证自定义分配器在极限情况下是否能正常工作。
 */
void test_edge_cases() {
    // 空字符串测试
    TlsfString empty_string;
    assert(empty_string.empty());

    // 小字符串测试
    TlsfString small_string("A");
    assert(small_string == "A");

    // 超大分配测试
    try {
        TlsfString huge_string;
        huge_string.resize(static_cast<size_t>(-1)); // 极端大分配
        assert(false && "Should not reach here");   // 应该抛出异常
    } catch (const std::bad_alloc&) {
        std::cout << "Caught expected std::bad_alloc for huge allocation.\n";
    }

    std::cout << "Edge cases test passed.\n";
}

/**
 * ### 6. **内存泄漏测试**
 *
 * 确保自定义分配器没有内存泄漏。
 * 在 Linux 下可以使用 `valgrind` 工具来检查是否有内存泄漏：
 * ```bash
 * valgrind --leak-check=full ./your_test_program
 * ```
 *
 * 代码部分加入释放分配器资源的逻辑（如果需要）：
```cpp
// 在程序退出时释放自定义分配器资源
void cleanup_allocator() {
    TlsfAllocator<char>::release_pool();
}
```
*/

/**
 * ### 主函数整合
 *
 * 将上述测试整合到主函数中运行：
 */

int main()
{
    try {
        test_basic_operations();
    } catch (const std::exception& e) {
        std::cerr << "test_basic_operations failed: " << e.what() << std::endl;
    }

    try {
        test_large_string();
    } catch (const std::exception& e) {
        std::cerr << "test_large_string failed: " << e.what() << std::endl;
    }

    try {
        //test_multithreading();
    } catch (const std::exception& e) {
        std::cerr << "test_multithreading failed: " << e.what() << std::endl;
    }

    try {
        test_performance();
    } catch (const std::exception& e) {
        std::cerr << "test_performance failed: " << e.what() << std::endl;
    }

    try {
        test_edge_cases();
    } catch (const std::exception& e) {
        std::cerr << "test_edge_cases failed: " << e.what() << std::endl;
    }

    std::cout << "All tests passed.\n";
    return 0;
}
